package com.telenav;

import java.awt.Dimension;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.imageio.ImageIO;

public class TTPlaneCrack implements TTCrack {

	public static int DIFF_THRESHOULD = 6;

	public static boolean DEBUG = false;
	public int last_x1 = -1;
	public int last_x2 = -1;
	public int last_y1 = -1;
	public int last_y2 = -1;

	private int leftBound = -1;

	private int rightBound = -1;

	/**
	 * @param args
	 * @throws Exception 
	 */
	public static void main(String[] args) throws Exception {
		BufferedImage bufferedImage = ImageIO.read(new File("E:\\tt\\capture.bmp"));
		new TTPlaneCrack().crackMove(null, null, bufferedImage);
	}

	public void crackMove(Robot robot, Dimension scrSize, BufferedImage bufferedImageFile) throws Exception {
		BufferedImage origBufferedImage;
		if (bufferedImageFile == null) {
			origBufferedImage = robot.createScreenCapture(new Rectangle(scrSize));
		} else {
			origBufferedImage = bufferedImageFile;
		}
		if (DEBUG) {
			ImageIO.write(origBufferedImage, "BMP", new File("E:\\tt\\capturefj+" + System.currentTimeMillis() + ".bmp"));
		}

		BufferedImage pTo = new BufferedImage(origBufferedImage.getWidth(), origBufferedImage.getHeight(), origBufferedImage.getType());
		ImgProcess.AutoThreshold(origBufferedImage, pTo);
		BufferedImage bufferedImage = ImgProcess.copyImage(pTo);

		if (DEBUG) {
			ImageIO.write(bufferedImage, "BMP", new File("E:\\tt\\out.bmp"));
		}

		int x1 = -1;
		int y1 = -1;
		int x2 = -1;
		int y2 = -1;
		if (last_x1 == -1) {
			int x = 0;
			int y = -1;
			boolean shouldBreak = false;
			for (int j = bufferedImage.getHeight() - 1; j > 100 && !shouldBreak; j--) {
				for (int i = 0; i < bufferedImage.getWidth(); i++) {
					int count = 0;
					if (ImgProcess.GetGray(bufferedImage, i, j) == 0 && ImgProcess.GetGray(bufferedImage, i, j - 1) > 0) {
						int mCount = 0;
						for (int m = 1; m < 101; m++) {
							if (ImgProcess.GetGray(bufferedImage, i, j - m) > 0) {
								mCount++;
							} else {
								break;
							}
						}
						if (mCount == 100) {
							int k = i;
							for (; k < bufferedImage.getWidth(); k++) {
								if (ImgProcess.GetGray(bufferedImage, k, j) == 0 && ImgProcess.GetGray(bufferedImage, k, j - 1) > 0) {

									int nCount = 0;
									for (int n = 1; n < 101; n++) {
										if (ImgProcess.GetGray(bufferedImage, k, j - n) > 0) {
											nCount++;
										} else {
											break;
										}
									}
									if (nCount == 100) {
										count++;
									}
								} else {
									break;
								}
							}
							if (count > 200) {
								y = j;
								x = i;
								System.out.println(x + "," + y);
								shouldBreak = true;
								break;
							}
							i = k;
						}
					}
				}
			}

			if (y == -1) {
				return;
			}
			ArrayList<BlackLine> blackLines = new ArrayList<BlackLine>();
			shouldBreak = false;
			for (int j = y; j > 0 && !shouldBreak; j--) {
				for (int i = 0; i < bufferedImage.getWidth(); i++) {
					int count = 0;
					if (ImgProcess.GetGray(bufferedImage, i, j) == 0) {
						int k = i;
						for (; k < bufferedImage.getWidth(); k++) {
							if (ImgProcess.GetGray(bufferedImage, k, j) == 0) {
								count++;
							} else {
								break;
							}
						}
						if (count > 6 && count < 200) {
							blackLines.add(new BlackLine(i, j, k, j, count));
							if (blackLines.size() == 3) {
								if (blackLines.get(1).x1 - blackLines.get(0).x2 < 200 && blackLines.get(2).x1 - blackLines.get(1).x2 < 200
										&& blackLines.get(1).count > blackLines.get(0).count && blackLines.get(1).count > blackLines.get(2).count) {
									System.out.println(blackLines);
									if (DEBUG) {
										for (BlackLine blackLine : blackLines) {
											for (int t = blackLine.x1; t < blackLine.x2 + 1; t++) {
												bufferedImage.setRGB(t, blackLine.y1, ImgProcess.getRGB(255, 0, 0));
											}
										}
										ImageIO.write(bufferedImage, "BMP", new File("E:\\tt\\out.bmp"));
									}
									x1 = blackLines.get(0).x1;
									x2 = blackLines.get(2).x2;
									y1 = blackLines.get(0).y1;
									shouldBreak = true;
								}
							}
						}
						i = k;
					}
				}
				blackLines = new ArrayList<BlackLine>();
			}

			if (x1 != -1) {
				for (int j = y1 - 1; j > 0; j--) {
					int i = x1;
					for (; i < x2; i++) {
						if (ImgProcess.GetGray(bufferedImage, i, j) == 0) {
							break;
						}
					}
					if (i == x2) {
						System.out.println(j);
						y2 = j;
						if (DEBUG) {
							for (int t = x1; t < x2 + 1; t++) {
								bufferedImage.setRGB(t, j, ImgProcess.getRGB(255, 0, 0));
							}

							ImageIO.write(bufferedImage, "BMP", new File("E:\\tt\\out.bmp"));
						}
						break;
					}
				}
			}
		} else {
			x1 = last_x1;
			y1 = last_y1;
			x2 = last_x2;
			y2 = last_y2;
		}

		if (y2 != -1) {
			if (leftBound == -1) {
				leftBound = x1 - 200;
				rightBound = x2 + 200;
			}
			//int speed = moveSpeed(bufferedImage, x1, x2, y2, y1);
			int speed = 5;
			if (speed != 0) {
				System.out.println("not safe, now move x1=" + x1 + ",x2=" + x2 + ",speed=" + speed);
				if (x1 - speed > leftBound) {
					if (robot != null) {
						robot.mouseMove(x1, y2);
						robot.mousePress(InputEvent.BUTTON1_MASK);
						robot.delay(5);
						robot.mouseMove(x1 - speed, y2);
						robot.mouseRelease(InputEvent.BUTTON1_MASK);
						robot.delay(5);
					}
					x1 = x1 - speed;
					x2 = x2 - speed;
				} else if (x2 + speed < rightBound) {
					if (robot != null) {
						robot.mouseMove(x1, y2);
						robot.mousePress(InputEvent.BUTTON1_MASK);
						robot.delay(5);
						robot.mouseMove(x1 + speed, y2);
						robot.mouseRelease(InputEvent.BUTTON1_MASK);
						robot.delay(5);
					}
					x1 = x1 + speed;
					x2 = x2 + speed;
				} else {
					System.out.println("error, can't move");
				}
			}
			last_x1 = x1;
			last_y1 = y1;
			last_x2 = x2;
			last_y2 = y2;

		}
	}

	public int moveSpeed(BufferedImage bufferedImage, int x1, int x2, int y2, int y1) {
		int count = 0;
		count = getBlackCount(bufferedImage, x1, x2, y2, 50);
		if (count > 10) {
			int ret = getBlackCount(bufferedImage, x1 - (x2 - x1), x2 - (x2 - x1), y1, y2 - y1);
			if (ret > 10) {
				ret = getBlackCount(bufferedImage, x1 + (x2 - x1), x2 + (x2 - x1), y1, y2 - y1);
				if (ret > 10) {
					ret = getBlackCount(bufferedImage, x1 + (x2 - x1) * 2, x2 + (x2 - x1) * 2, y1, y2 - y1);
					if (ret > 10) {
						ret = getBlackCount(bufferedImage, x1 - (x2 - x1) * 2, x2 - (x2 - x1) * 2, y1, y2 - y1);
						if (ret > 10) {
							return 0;
						} else {
							return -(x2 - x1) * 2;
						}
					} else {
						return (x2 - x1) * 2;
					}
				} else {
					return (x2 - x1);
				}
			} else {
				return -(x2 - x1);
			}
		} else {
			return 0;
		}
	}

	public int getBlackCount(BufferedImage bufferedImage, int x1, int x2, int y, int h) {
		int count = 0;
		boolean shouldBreak = false;
		for (int j = y; j > y - h && !shouldBreak; j--) {
			for (int i = x1; i < x2; i++) {
				if (ImgProcess.GetGray(bufferedImage, i, j) == 0) {
					count++;
				}
				if (count > 10) {
					shouldBreak = true;
					break;
				}
			}
		}
		return count;
	}

	class BlackLine {
		int x1;
		int y1;
		int x2;
		int y2;
		int count;

		public BlackLine(int x1, int y1, int x2, int y2, int count) {
			this.x1 = x1;
			this.x2 = x2;
			this.y1 = y1;
			this.y2 = y2;
			this.count = count;
		}

		public String toString() {
			return x1 + "," + y1 + "-" + x2 + "," + y2 + "-" + count;
		}
	}
}
